﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NewsDiscoveryEngine;
using NewsMine.DomainObjects;
using NewsMine.Storage.SQLite;
using System.IO;
using NewsMine.Storage;
using NewsMine.Utilities;
using System.Data.SQLite;
using LuceneWrap.Lib;


public partial class frmMigration : Form
{
    public frmMigration()
    {
        InitializeComponent();
    }

    /// <summary>
    /// This function should copy the existing feed from index / feedDataStore to brand new sql store.
    /// 
    /// here the feed's all teh fields needs to get saved in the sql store.
    /// 
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnCopyFeedToSqlStore_Click(object sender, EventArgs e)
    {
        CopyFeedsFromLuceneFeedIndexToSqliteStore();
    }

    private void CopyFeedsFromLuceneFeedIndexToSqliteStore()
    {
        var indxer = FeedIndexSearcher.Instance;

        //var indxer = FeedIndexer.Instance;
        //indxer.SetStagingOn();
        int recsPerPage = 1000;
        int totalRecs = 0;

        List<FeedItem> feeds = new List<FeedItem>();
        bool isNextSetResultsAvailable = false;

        string sqliteFilePath = "c:\\SqliteStoreForFeeds.db";
        SQLiteFeedStoreHelper target = new SQLiteFeedStoreHelper(sqliteFilePath);

        int pagenumber = 0;

        do
        {
            feeds = indxer.GetFeedItemsByQuery("*:*", pagenumber, recsPerPage, out totalRecs);

            target.AddFeedToStore(feeds);

            if (feeds.Count > 0)
            {
                isNextSetResultsAvailable = true;
            }
            else
                isNextSetResultsAvailable = false;

            pagenumber++;

        }
        while (isNextSetResultsAvailable);


        MessageBox.Show("done.");

    }

    private void btnCopyFeedFromSqlToLucene_Click(object sender, EventArgs e)
    {

        var indxer = FeedIndexer.Instance;

        //var indxer = FeedIndexer.Instance;
        //indxer.SetStagingOn();
        int recsPerPage = 100;
        int totalRecs = 0;

        List<FeedItem> feeds = new List<FeedItem>();
        bool isNextSetResultsAvailable = false;

        string sqliteFilePath = "c:\\SqliteStoreForFeeds.db";
        SQLiteFeedStoreHelper sqliteFeedStore = new SQLiteFeedStoreHelper(sqliteFilePath);

        long startId = 0;
        long nextStartId = 0;

        int retrivedCount = 0;

        do
        {
            feeds = sqliteFeedStore.GetAllByPage(startId, recsPerPage, out nextStartId);

            retrivedCount = retrivedCount + feeds.Count;

            indxer.IndexFeedItems(feeds);

            //feeds = indxer.GetFeedItemsByQuery("*:*", pagenumber, recsPerPage, out totalRecs);

            startId = nextStartId;

            if (feeds.Count > 0)
            {
                isNextSetResultsAvailable = true;
            }
            else
                isNextSetResultsAvailable = false;



        }
        while (isNextSetResultsAvailable);



        MessageBox.Show("done.");

    }

    private void btnCopyWebsitesMasterDataToSqlStore_Click(object sender, EventArgs e)
    {
        //just copy all the websiteinfo master data from the lucenen based index store to sqlite key value store.

        // here better check if the sqlite file is already avalialbe, if avaialable alert user to take decision on deleting or not.

        // if the user says no for the deletion, just quit from the method.


        // if user user says yes for deletion, go ahead and delete the sqlite file and read the data from the lucene indiex keyvalues to the sqlite kv store.
        string webMasterLuceneFolder = Path.Combine(NewsMine.Configuration.ConfigurationManager.StorageBaseFolder, @"KeyValueStores\WebSiteInfoMasterStore");

        var luceneKeyValueStore = new KeyValueStoreOnFileSystem(webMasterLuceneFolder);

        int count = luceneKeyValueStore.GetCount();

        var websiteObjects = luceneKeyValueStore.Get(0, count + 1);

        var webSites = new List<WebSiteInfo>();


        var webMasterOnSqliteKVStore = Defaults.WebSiteInfoMasterStore;

        webMasterOnSqliteKVStore.Open();

        foreach (var websiteInfoObject in websiteObjects)
        {
            WebSiteInfo wbSiteInfo = (WebSiteInfo)websiteInfoObject;
            //if (wbSiteInfo.MenuItemconfigs != null && wbSiteInfo.MenuItemconfigs.Count > 0)
            webSites.Add(wbSiteInfo);

            webMasterOnSqliteKVStore.Replace(wbSiteInfo.Domain, wbSiteInfo);
        }

        webMasterOnSqliteKVStore.Close();

        if (webMasterOnSqliteKVStore.GetCount() == webMasterOnSqliteKVStore.GetCount())
        {
            MessageBox.Show("Successfully webinfo is transferred to  Sqlite Store");
        }
        else
            MessageBox.Show("Some issue, not properly copied all the webinfo to sqlite store");
    }


    BackgroundWorker bgWorker;
    private void btnUpdateAlexaRanks_Click(object sender, EventArgs e)
    {
        bgWorker = new BackgroundWorker();
        bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
        bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
        bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);

        bgWorker.RunWorkerAsync();
    }

    void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            MessageBox.Show("Error while alexa udpate.  " + e.Error.Message);
        }
        else
        {
            MessageBox.Show("All the alexa updates done successfully.");
        }

    }

    void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.Text = e.ProgressPercentage.ToString() + " % ; " + e.UserState.ToString();
    }

    void bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        UpdateAlexaRanks();
    }

    private void UpdateAlexaRanks()
    {
        var wesiteMaster = Defaults.WebSiteInfoMasterStore;

        var domains = NewsMine.DataManagers.WebSiteInfoManager.GetAllDomains(true);

        for (int i = 0; i < domains.Count; i++)
        {
            domains[i].AlexaRank = NewsMine.Utilities.AlexaHelper.GetAlexaRank(domains[i].Domain);
            wesiteMaster.Replace(domains[i].Domain, domains[i]);
            bgWorker.WorkerReportsProgress = true;
            bgWorker.ReportProgress(Convert.ToInt32((i / domains.Count) * 100), i.ToString() + " / " + domains.Count.ToString() + " : " + domains[i].Domain + " => " + domains[i].AlexaRank.ToString());

            System.Threading.Thread.Sleep(1000);
        }
    }

    private void btnReIndexSelfMode_Click(object sender, EventArgs e)
    {
        try
        {
            FeedIndexer indexer = FeedIndexer.Instance;

            indexer.DoSelfReIndex();
            MessageBox.Show("Re Indexing is done...");

        }
        catch (Exception ex)
        {
            TempLogger.LogCustom("reindexingErrors.txt", ex.Message + Environment.NewLine + ex.StackTrace);
            MessageBox.Show("errored");
        }
    }

    private void btnReIndexFromSqlite_Click(object sender, EventArgs e)
    {
        var result = MessageBox.Show("Are you sure", "", MessageBoxButtons.YesNo);

        if (result == System.Windows.Forms.DialogResult.No)
            return;

        try
        {
            FeedIndexer indexer = FeedIndexer.Instance;

            indexer.ReindexFromSqliteStore();
            MessageBox.Show("Re Indexing is done...");

        }
        catch (Exception ex)
        {
            TempLogger.LogCustom("reindexingErrors.txt", ex.Message + Environment.NewLine + ex.StackTrace);
            MessageBox.Show("errored");
        }
    }

    private void btnRebuildTitleAndLinkIndexes_Click(object sender, EventArgs e)
    {
        //SQLiteKeyValueStore linkKVStore = (SQLiteKeyValueStore)Defaults.UniqueHtmlFeedLinkStore;

        //var sqliteHelper = linkKVStore.GetSqliteHelperClass();

        //string folder = linkKVStore.GetStoreDirectory();

        RebuildLinkStore();

    }

    private void RebuildLinkStore()
    {
        // ----------------- SETUP INDEX STORE STUFF

        bool isNextSetResultsAvailable = false;
        int docIndexCounter = 0;
        FeedItem tempFeedItem = null;
        var luceneManager = FeedIndexer.Instance.GetLuceneManager();

        luceneManager.Create();

        var indexReader = luceneManager.IndexWriter.GetReader();
        int maxDoc = indexReader.MaxDoc();

        if (maxDoc == 0)
            return;

        // ----------------- SETUP THE SQLITE STORE STUFF-------------------

        SQLiteKeyValueStore linkKVStore = (SQLiteKeyValueStore)Defaults.UniqueHtmlFeedLinkStore;

        var linkSqliteHelper = linkKVStore.GetSqliteHelperClass();

        string linkFolderPath = linkKVStore.GetStoreDirectory();

        string filePath = Path.Combine(linkFolderPath, "sqliteKVItems.db");

        string linkConnectionString = string.Format("Data Source={0};Version=3;Pooling=True;Max Pool Size=100;UTF8Encoding=True", filePath);

        var linkConnection = new SQLiteConnection(linkConnectionString);

        byte[] data = { Convert.ToByte(false) };

        linkConnection.Open();

        Dictionary<string, int> dedupDictionary = new Dictionary<string, int>();

        using (SQLiteTransaction tran = linkConnection.BeginTransaction())
        {
            try
            {
                using (var command = new SQLiteCommand("delete from KeyValue", linkConnection))
                {
                    command.ExecuteNonQuery();
                }

                do
                {
                    //LogReIndexStatus("above read document at index " + docIndexCounter);
                    var d = indexReader.Document(docIndexCounter);

                    tempFeedItem = null;

                    tempFeedItem = LuceneReflection.GetObjFromDocument<FeedItem>(d);

                    if (tempFeedItem != null && !string.IsNullOrEmpty(tempFeedItem.Link))
                    {

                        //---------------- Just insert key into the sqlite

                        string key = TempAnalyzer.RemoveAllSpecialCharacterForIndexing(tempFeedItem.Link).Replace(" ", string.Empty);

                     
                        if (!string.IsNullOrEmpty(key))
                        {
                            key = key.ToLower();

                            if (!dedupDictionary.ContainsKey(key))
                            {
                                dedupDictionary.Add(key, 1);


                                using (var command = new SQLiteCommand("INSERT INTO KeyValue (KEY,DATA) VALUES (@key,@data)", linkConnection))
                                {
                                    command.Parameters.Add("@key", DbType.String, key.Length).Value = key;
                                    if (data != null)
                                        command.Parameters.Add("@data", DbType.Binary, data.Length).Value = data;
                                    else
                                        command.Parameters.Add("@data", DbType.Binary, 0).Value = null;

                                    command.ExecuteNonQuery();
                                }
                            }
                            else
                            {
                                dedupDictionary[key] = dedupDictionary[key] + 1;
                            }
                        }

                    }

                    docIndexCounter = docIndexCounter + 1;

                    if (docIndexCounter >= maxDoc)
                        isNextSetResultsAvailable = false;
                    else
                        isNextSetResultsAvailable = true;
                }
                while (isNextSetResultsAvailable);

                luceneManager.FinalizeWriter(true);

                tran.Commit();


            }
            catch (Exception ex)
            {
                tran.Rollback();
                throw;
            }
        }


    }

}

